﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MobMentality.Map;
using Microsoft.Xna.Framework;

namespace MobMentality.Social
{
	class PersonNavigator
	{
		private IMapNavigate navigationMap;

		static PersonNavigator instance;

		public static PersonNavigator Instance
		{
			get
			{
				if (instance == null)
				{
					instance = new PersonNavigator();
				}
				return instance;
			}
		}

		public IMapNavigate NavigationMap
		{
			set
			{
				navigationMap = value;
			}
		}

		public void movePerson(Person person)
		{
			Vector2 move = new Vector2();
			float speed = 1.0f;
			float comfortDistance = 30.0f;

			if (person.MapPosition.X < person.TargetPoint.X - speed)
			{
				move.X = speed;
			}
			else if (person.MapPosition.X > person.TargetPoint.X + speed)
			{
				move.X = -speed;
			}

			if (person.MapPosition.Y < person.TargetPoint.Y - speed)
			{
				move.Y = speed;
			}
			else if (person.MapPosition.Y > person.TargetPoint.Y + speed)
			{
				move.Y = -speed;
			}

			/*Handles collision between group members (flocking sort of)*/
			Vector2 correction = Vector2.Zero;
            Vector2 groupVelocity = Vector2.Zero;
            Vector2 centerOfMass = person.MapPosition;
            int personCount = 1;
			//Ugly Loop
			foreach (Person other in PeopleHolder.Instance.PeopleInArea(person.MapPosition, comfortDistance))
			{
				if (person == other)
				{
					continue;
				}
                personCount++;
                groupVelocity += other.Velocity;
                centerOfMass += other.MapPosition;
				Vector2 separate = person.MapPosition - other.MapPosition;
                if (separate.X <= comfortDistance && separate.Y <= comfortDistance)
				{
					person.Move(new Vector2(1,1));
				}
				separate.Normalize();
				correction += separate;
			}
            if (personCount > 1)
            {
                groupVelocity = groupVelocity / personCount;
            }
            centerOfMass = (person.MapPosition - (centerOfMass / personCount)) / 10;
            correction += groupVelocity / 8;
            correction += centerOfMass;
			if (correction != Vector2.Zero)
			{
				move += correction;
			}

			if (navigationMap.isNavigable(navigationMap.GetTile(person.MapPosition + move*(30/speed))))
			{
				person.Move(move);
				Point tile = navigationMap.GetTile(person.MapPosition);
				Vector2 inTilePosition = new Vector2(person.MapPosition.X - navigationMap.GetMapPosition(tile).X, 
														person.MapPosition.Y - navigationMap.GetMapPosition(tile).Y);

				Point currentPosition = new Point((int)(inTilePosition.X / (navigationMap.TileWidth / 3)),
													(int)(inTilePosition.Y / (navigationMap.TileHeight / 3)));

				//freaking border conditions
				if (currentPosition.X > 2)
				{
					currentPosition.X = 2;
				}

				if (currentPosition.Y > 2)
				{
					currentPosition.Y = 2;
				}

				person.currentSubPosition = currentPosition;
			}

			if (person.Team == Team.Riot)
			{
				navigationMap.Capture(navigationMap.GetTile(person.MapPosition));
			}
		}

		public int estimateMapDistance(Vector2 start, Vector2 end)
		{
			Point tileStart = navigationMap.GetTile(start);
			Point tileEnd = navigationMap.GetTile(end);

			return navigationMap.AStarDistance(tileStart, tileEnd, delegate(Point point1, Point point2) { return (point2.X - point1.X) + (point2.Y - point1.Y); });
		}
	}
}
